#include "../zepto.h"
#include "../internal.h"

DECLARE_FOREIGN("+", builtin_plus, NO_ARGS, EVAL_NONE, IGNORE_TAIL, EVAL_TAIL)
{
  long sum = 0;
  while(tail->type == ZEPTO_PAIR) {
    CHECK_TYPE(CAR(tail), ZEPTO_INTEGER);
    sum += CAR(tail)->data.integer;
    tail = CDR(tail);
  }
  CHECK_TYPE(tail, ZEPTO_NIL);
  return _make_zepto_number(sum);
}

DECLARE_FOREIGN("-", builtin_minus, ONE_ARG, EVAL_FIRST, IGNORE_TAIL, EVAL_TAIL)
{
  long sum;

  CHECK_TYPE(arg1, ZEPTO_INTEGER);
  
  sum = arg1->data.integer;
  
  while(tail->type == ZEPTO_PAIR) {
    CHECK_TYPE(CAR(tail), ZEPTO_INTEGER);
    sum -= CAR(tail)->data.integer;
    tail = CDR(tail);
  }
  CHECK_TYPE(tail, ZEPTO_NIL);
  return _make_zepto_number(sum);
}

DECLARE_FOREIGN("*", builtin_mul, NO_ARGS, EVAL_NONE, IGNORE_TAIL, EVAL_TAIL)
{
  long res = 1;
  
  while(tail->type == ZEPTO_PAIR) {
    CHECK_TYPE(CAR(tail), ZEPTO_INTEGER);
    res *= CAR(tail)->data.integer;
    tail = CDR(tail);
  }
  CHECK_TYPE(tail, ZEPTO_NIL);
  return _make_zepto_number(res);
}

DECLARE_FOREIGN("/", builtin_div, ONE_ARG, EVAL_FIRST, IGNORE_TAIL, EVAL_TAIL)
{
  long res;

  CHECK_TYPE(arg1, ZEPTO_INTEGER);
  
  res = arg1->data.integer;
  
  while(tail->type == ZEPTO_PAIR) {
    CHECK_TYPE(CAR(tail), ZEPTO_INTEGER);
    res /= CAR(tail)->data.integer;
    tail = CDR(tail);
  }
  CHECK_TYPE(tail, ZEPTO_NIL);
  return _make_zepto_number(res);
}


void register_math(void)
{
  EXPORT_FOREIGN(builtin_plus);
  EXPORT_FOREIGN(builtin_minus);
  EXPORT_FOREIGN(builtin_mul);
  EXPORT_FOREIGN(builtin_div);
}
